﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

namespace hxy.CopyRight
{
	/// <summary>
	/// 产品的注册管理器
	/// </summary>
	public class ProductRegister
	{
		/// <summary>
		/// 注册成功后的信息，需要由这个提供器提供。
		/// </summary>
		public static IRegisterInfoProvider RegisterInfoProvider { get; set; }

		/// <summary>
		/// 使用指定的注册码进行注册。
		/// </summary>
		/// <param name="registerCode">
		/// 从供应商处获取到的注册码。
		/// </param>
		public static void Register(string registerCode)
		{
			CheckProvider();

			var info = RegisterCodeManager.DecryptCode(registerCode);
			if (info.RegisterTimeLimit <= DateTime.Now)
			{
				throw new ArgumentException("注册码注册时间已经过期。");
			}
			if (info.UseTimeLimit <= DateTime.Now)
			{
				throw new ArgumentException("使用时间已经过期，无法使用。");
			}

			string mac = GetMAC();
			var persistentInfo = EncryptToDisk(new SuccessInfo()
			{
				MAC = mac,
				UseTimeLimit = info.UseTimeLimit
			});

			RegisterInfoProvider.SaveRegisterInfo(persistentInfo);
		}

		/// <summary>
		/// 清除注册成功的信息。
		/// </summary>
		public static void Clear()
		{
			CheckProvider();
			RegisterInfoProvider.Clear();
		}

		/// <summary>
		/// 产品使用此方法来检测是否已经注册成功。
		/// 如果注册成功，则一并返回可以使用的期限。
		/// </summary>
		/// <param name="useTimeLimit">产品可以使用的期限</param>
		/// <returns></returns>
		public static bool HasRegistered(out DateTime useTimeLimit)
		{
			useTimeLimit = default(DateTime);

			CheckProvider();
			var persistentInfo = RegisterInfoProvider.GetRegisterInfo();

			if (string.IsNullOrWhiteSpace(persistentInfo)) return false;

			var info = DecryptFromDisk(persistentInfo);
			var mac = GetMAC();
			if (string.Compare(mac, info.MAC, true) != 0) return false;

			useTimeLimit = info.UseTimeLimit;
			return true;
		}

		/// <summary>
		/// 获取当前机器的MAC地址。
		/// </summary>
		/// <returns></returns>
		private static string GetMAC()
		{
			var manager = new ManagementClass("Win32_NetworkAdapterConfiguration");
			var MOC = manager.GetInstances();

			foreach (var MO in MOC)
			{
				if ((bool)MO["IPEnabled"])
				{
					return MO["MACAddress"].ToString();
				}
			}

			throw new NotSupportedException("无法获取当前主机的MAC地址！");
		}

		/// <summary>
		/// 保证当前提供器已经注入。
		/// </summary>
		private static void CheckProvider()
		{
			if (RegisterInfoProvider == null) throw new InvalidOperationException("请先设置RegisterInfoProvider属性。");
		}

		#region Encrypto

		private static readonly string _infoSplitter = ",";

		private static readonly string _infoEncryptPWD = "hxy";

		/// <summary>
		/// 把注册成功后的信息，加密为一个可以存储的字符串。
		/// </summary>
		/// <param name="info"></param>
		/// <returns></returns>
		private static string EncryptToDisk(SuccessInfo info)
		{
			var strInfo = info.MAC + _infoSplitter + info.UseTimeLimit.Ticks;
			return DES.Encrypt(strInfo, _infoEncryptPWD);
		}

		/// <summary>
		/// 从字符串中获取注册完成后的信息。
		/// </summary>
		/// <param name="info"></param>
		/// <returns></returns>
		private static SuccessInfo DecryptFromDisk(string info)
		{
			var strInfo = DES.Decrypt(info, _infoEncryptPWD);
			var infos = strInfo.Split(_infoSplitter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
			if (infos.Length != 2) throw new InvalidOperationException("infos.Length != 2 must be false.");

			return new SuccessInfo()
			{
				MAC = infos[0],
				UseTimeLimit = new DateTime(long.Parse(infos[1]))
			};
		}

		#endregion
	}

	/// <summary>
	/// 注册完成后的信息。
	/// </summary>
	internal class SuccessInfo
	{
		/// <summary>
		/// 当前机器的MAC地址。
		/// </summary>
		public string MAC { get; set; }

		/// <summary>
		/// 可以使用的产品期限。
		/// </summary>
		public DateTime UseTimeLimit { get; set; }
	}
}
